

#include <wx/wx.h>
#include <wx/button.h>
#include <wx/filedlg.h>
#include <wx/msgdlg.h>
#include <wx/choice.h>
#include <wx/dcbuffer.h>
#include <wx/brush.h>
#include <wx/pen.h>
#include <fstream>
#include <vector>
#include <sstream>
#include <algorithm>

class ChartFrame : public wxFrame {
public:
    // 构造函数，初始化框架
    ChartFrame(const wxString& title)
        : wxFrame(nullptr, wxID_ANY, title, wxDefaultPosition, wxSize(800, 600)),
        m_data(), m_selectedMode(0) {
        // 设置背景样式
        SetBackgroundStyle(wxBG_STYLE_PAINT);

        // 创建一个按钮，用于触发文件对话框
        m_button = new wxButton(this, wxID_ANY, "Load CSV and Draw Chart", wxDefaultPosition, wxSize(200, 50));

        // 创建一个选择框，用于选择显示模式
        m_choice = new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
            { "Single Threaded", "Non-Preemptive Multithreaded", "Preemptive Multithreaded" });
        m_choice->Bind(wxEVT_CHOICE, &ChartFrame::OnChoiceSelected, this);

        // 绑定按钮点击事件
        m_button->Bind(wxEVT_BUTTON, &ChartFrame::OnButtonClicked, this);

        // 设置布局管理器
        wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL);
        sizer->Add(m_button, 0, wxALIGN_CENTER | wxALL, 10);
        sizer->Add(m_choice, 0, wxALIGN_CENTER | wxALL, 10);
        SetSizer(sizer);

        // 绑定绘图事件
        Bind(wxEVT_PAINT, &ChartFrame::OnPaint, this);
    }

private:
    // 处理按钮点击事件，打开文件对话框并读取CSV文件
    void OnButtonClicked(wxCommandEvent& event) {
        // 打开文件对话框
        wxFileDialog openFileDialog(this, _("Open CSV file"), "", "", "CSV files (*.csv)|*.csv", wxFD_OPEN | wxFD_FILE_MUST_EXIST);
        if (openFileDialog.ShowModal() == wxID_CANCEL) {
            return; // 用户取消了选择
        }

        // 读取文件
        std::string filename = openFileDialog.GetPath().ToStdString();
        m_data = ReadCSV(filename);

        // 重新绘制窗口
        Refresh();
    }

    // 处理选择框事件，更新显示模式
    void OnChoiceSelected(wxCommandEvent& event) {
        m_selectedMode = event.GetSelection();
        Refresh();
    }

    // 从CSV文件中读取数据，存储在二维数组中
    std::vector<std::vector<int>> ReadCSV(const std::string& filename) {
        std::ifstream file(filename);
        std::vector<std::vector<int>> data;

        if (file.is_open()) {
            std::string line;
            while (std::getline(file, line)) {
                std::istringstream iss(line);
                std::vector<int> process;

                // 读取每行的三个时间值
                std::string token;
                int calculationTime1, ioTime, calculationTime2;
                std::getline(iss, token, ','); // 读取第一个计算时间
                calculationTime1 = std::stoi(token);
                std::getline(iss, token, ','); // 读取I/O时间
                ioTime = std::stoi(token);
                std::getline(iss, token, ','); // 读取第二个计算时间
                calculationTime2 = std::stoi(token);

                // 将读取的时间值存储到子数组中
                process.push_back(calculationTime1);
                process.push_back(ioTime);
                process.push_back(calculationTime2);

                // 将子数组添加到主数组中
                data.push_back(process);
            }

            // 关闭文件
            file.close();
        }
        else {
            // 如果文件无法打开，记录错误信息              
            wxLogError(_("Unable to open file"));
        }

        return data;
    }

    // 处理绘图事件
    void OnPaint(wxPaintEvent& event) {
        // 创建一个自动缓冲的绘图设备上下文
        wxAutoBufferedPaintDC dc(this);
        PrepareDC(dc);

        // 清除背景
        dc.SetBackground(*wxWHITE_BRUSH);
        dc.Clear();

        // 如果没有数据，则不绘制任何东西
        if (m_data.empty()) {
            return;
        }

        // 计算绘图区域
        wxSize size = GetClientSize();
        int x_offset = 50; // X轴偏移量
        int y_offset = 50; // Y轴偏移量
        int width = size.x - 2 * x_offset;
        int height = size.y - 2 * y_offset;

        // 绘制坐标轴
        dc.DrawLine(x_offset, y_offset, x_offset, y_offset + height); // 纵轴
        dc.DrawLine(x_offset, y_offset + height, x_offset + width, y_offset + height); // 横轴

        // 绘制纵轴刻度
        dc.DrawLine(x_offset - 5, y_offset + height / 3, x_offset + 5, y_offset + height / 3); // 计算
        dc.DrawLine(x_offset - 5, y_offset + 2 * height / 3, x_offset + 5, y_offset + 2 * height / 3); // I/O

        wxString timeStr = wxString::Format("%d", 0);
        dc.DrawText(timeStr, x_offset, y_offset + height);

        // 绘制纵轴标签
        dc.DrawText("Cal", x_offset - 50, y_offset + height / 3 - 10);
        dc.DrawText("I/O", x_offset - 50, y_offset + 2 * height / 3 - 10);

        // 根据选择的模式绘制时间关系图
        switch (m_selectedMode) {
        case 0: // 单道程序
            DrawSingleThreadedChart(dc, x_offset, y_offset, width, height);
            break;
        case 1: // 非抢占式多道程序
            DrawNonPreemptiveMultithreadedChart(dc, x_offset, y_offset, width, height);
            break;
        case 2: // 抢占式多道程序
             DrawPreemptiveMultithreadedChart(dc, x_offset, y_offset, width, height);
            break;
        }
    }

    // 绘制单道程序的时间关系图
    void DrawSingleThreadedChart(wxDC& dc, int x_offset, int y_offset, int width, int height) {
        int currentTime = 0; // 当前时间，用于计算X轴位置

        int maxTime = 0; // 计算所有进程的总时间
        // 计算最大时间
        for (const auto& process : m_data) {
            maxTime += process[0] + process[1] + process[2];
        }

        wxFont smallFont(8, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
        dc.SetFont(smallFont);

        for (const auto& process : m_data) {
            // 计算第一个计算时间的起始和结束位置
            int startX = x_offset + (currentTime * width) / maxTime;
            int endX = startX + (process[0] * width) / maxTime;

            // 黑色实线表示计算时间
            wxPen calcPen(wxColor(0, 0, 0), 2, wxPENSTYLE_SOLID);
            dc.SetPen(calcPen);
            dc.DrawLine(startX, y_offset + height / 3, endX, y_offset + height / 3);

            wxPen ioPen(wxColor(0, 0, 0), 0.5, wxPENSTYLE_DOT);
            dc.SetPen(ioPen);
            dc.DrawLine(endX, y_offset + height / 3, endX, y_offset + height);

            // 更新当前时间
            currentTime += process[0];

            wxString timeStr = wxString::Format("%d", currentTime);
            dc.DrawText(timeStr, endX - 2, y_offset + height);


            // 计算I/O时间的起始和结束位置
            startX = endX;
            endX = startX + (process[1] * width) / maxTime;
            dc.SetPen(calcPen); // 表示I/O时间
            dc.DrawLine(startX, y_offset + 2 * height / 3, endX, y_offset + 2 * height / 3);


            // 更新当前时间
            currentTime += process[1];

            // 计算第二个计算时间的起始和结束位置
            startX = endX;
            endX = startX + (process[2] * width) / maxTime;
            dc.SetPen(calcPen); //表示计算时间
            dc.DrawLine(startX, y_offset + height / 3, endX, y_offset + height / 3);

            dc.SetPen(ioPen);
            dc.DrawLine(startX, y_offset + height / 3, startX, y_offset + height);

            timeStr = wxString::Format("%d", currentTime);
            dc.DrawText(timeStr, startX - 2, y_offset + height);

            dc.SetPen(ioPen);
            dc.DrawLine(endX, y_offset + height / 3, endX, y_offset + height);

            // 更新当前时间
            currentTime += process[2];

            timeStr = wxString::Format("%d", currentTime);
            dc.DrawText(timeStr, endX - 2, y_offset + height);
        }
    }

    // 绘制非抢占式多道程序的时间关系图
    void DrawNonPreemptiveMultithreadedChart(wxDC& dc, int x_offset, int y_offset, int width, int height) {
        int sum = 0;
        int n = m_data.size();

        // 黑色实线
        wxPen calcPen(wxColor(0, 0, 0), 2, wxPENSTYLE_SOLID);

        //虚线
        wxPen ioPen(wxColor(0, 0, 0), 0.5, wxPENSTYLE_DOT);


        //显示时间坐标数
        wxString timeStr = wxString::Format("%d", sum);

        // 深拷贝数据
        std::vector<std::vector<int>> m_datacp = m_data;

        int maxTime = 0; // 计算所有进程的总时间

        // 计算最大时间
        for (const auto& process : m_data) {
            maxTime += process[0] + process[1] + process[2];
        }

        //容器的名称
        int i = 0;
        int j = 0;
        int k = 0;

        while (k < n) {
            if (i == j && j == k) {

                int startX = x_offset + (sum * width) / maxTime;

                sum += m_datacp[i][0];

                int endX = startX + (m_datacp[i][0] * width) / maxTime;

                m_datacp[i][0] = 0;


                //实线
                dc.SetPen(calcPen);
                dc.DrawLine(startX, y_offset + height / 3, endX, y_offset + height / 3);

                //坐标轴数字
                timeStr = wxString::Format("%d", sum);
                dc.DrawText(timeStr, endX - 2, y_offset + height);

                i += 1;
            }
            else if (i < n && i > j && j == k) {
                if (m_datacp[i][0] > m_datacp[j][1]) {
                    int startX = x_offset + (sum * width) / maxTime;

                    m_datacp[i][0] -= m_datacp[j][1];

                    int endX = startX + (m_datacp[j][1] * width) / maxTime;

                    sum += m_datacp[j][1];
                    m_datacp[j][1] = 0;


                    dc.SetPen(calcPen);
                    dc.DrawLine(startX, y_offset + 2 * height / 3, endX, y_offset + 2 * height / 3);
                    dc.DrawLine(startX, y_offset + height / 3, endX, y_offset + height / 3);

                    timeStr = wxString::Format("%d", sum);
                    dc.DrawText(timeStr, endX - 2, y_offset + height);

                    j += 1;
                }
                else if (m_datacp[i][0] < m_datacp[j][1]) {
                    int startX = x_offset + (sum * width) / maxTime;

                    m_datacp[j][1] -= m_datacp[i][0];
                    sum += m_datacp[i][0];

                    int endX = startX + (m_datacp[i][0] * width) / maxTime;

                    m_datacp[i][0] = 0;


                    dc.SetPen(calcPen);
                    dc.DrawLine(startX, y_offset + height / 3, endX, y_offset + height / 3);
                    dc.DrawLine(startX, y_offset + 2 * height / 3, endX, y_offset + 2 * height / 3);

                    timeStr = wxString::Format("%d", sum);
                    dc.DrawText(timeStr, endX - 2, y_offset + height);

                    i += 1;
                }
                else {
                    int startX = x_offset + (sum * width) / maxTime;

                    sum += m_datacp[i][0];

                    int endX = startX + (m_datacp[i][0] * width) / maxTime;

                    m_datacp[i][0] = 0;
                    m_datacp[j][1] = 0;

                    dc.SetPen(calcPen);
                    dc.DrawLine(startX, y_offset + height / 3, endX, y_offset + height / 3);

                    timeStr = wxString::Format("%d", sum);
                    dc.DrawText(timeStr, endX - 2, y_offset + height);

                    dc.SetPen(calcPen);
                    dc.DrawLine(startX, y_offset + 2 * height / 3, endX, y_offset + 2 * height / 3);

                    i += 1;
                    j += 1;
                }
            }
            else if (i == n && i > j && j == k) {
                int startX = x_offset + (sum * width) / maxTime;

                sum += m_datacp[j][1];

                int endX = startX + (m_datacp[j][1] * width) / maxTime;

                m_datacp[j][1] = 0;

                dc.SetPen(calcPen);
                dc.DrawLine(startX, y_offset + 2 * height / 3, endX, y_offset + 2 * height / 3);

                timeStr = wxString::Format("%d", sum);
                dc.DrawText(timeStr, endX - 2, y_offset + height);

                j += 1;
            }
            else if (i < n && m_datacp[i][0] == 0 && i == j && j > k) {
                int startX = x_offset + (sum * width) / maxTime;

                sum += m_datacp[k][2];

                int endX = startX + (m_datacp[k][2] * width) / maxTime;

                m_datacp[k][2] = 0;


                dc.SetPen(calcPen);
                dc.DrawLine(startX, y_offset + height / 3, endX, y_offset + height / 3);

                timeStr = wxString::Format("%d", sum);
                dc.DrawText(timeStr, endX - 2, y_offset + height);

                k += 1;
            }
            else if (i < n && m_datacp[i][0] > 0 && m_datacp[i][0] != m_data[i][0] && i == j && j > k) {
                int startX = x_offset + (sum * width) / maxTime;

                sum += m_datacp[i][0];

                int endX = startX + (m_datacp[i][0] * width) / maxTime;

                m_datacp[i][0] = 0;

                dc.SetPen(calcPen);
                dc.DrawLine(startX, y_offset + height / 3, endX, y_offset + height / 3);

                timeStr = wxString::Format("%d", sum);
                dc.DrawText(timeStr, endX - 2, y_offset + height);

                i += 1;
            }
            else if (i < n && m_datacp[i][0] > 0 && m_datacp[i][0] == m_data[i][0] && i == j && j > k) {
                int startX = x_offset + (sum * width) / maxTime;

                sum += m_datacp[k][2];

                int endX = startX + (m_datacp[k][2] * width) / maxTime;

                m_datacp[k][2] = 0;

                dc.SetPen(calcPen);
                dc.DrawLine(startX, y_offset + height / 3, endX, y_offset + height / 3);

                timeStr = wxString::Format("%d", sum);
                dc.DrawText(timeStr, endX - 2, y_offset + height);

                k += 1;
            }
            else if (i == n && i == j && j > k) {
                int startX = x_offset + (sum * width) / maxTime;

                sum += m_datacp[k][2];

                int endX = startX + (m_datacp[k][2] * width) / maxTime;

                m_datacp[k][2] = 0;

                dc.SetPen(calcPen);
                dc.DrawLine(startX, y_offset + height / 3, endX, y_offset + height / 3);

                timeStr = wxString::Format("%d", sum);
                dc.DrawText(timeStr, endX - 2, y_offset + height);

                k += 1;
            }
            else if (i > j && j > k) {
                if (m_datacp[j][1] > m_datacp[k][2]) {
                    int startX = x_offset + (sum * width) / maxTime;

                    m_datacp[j][1] -= m_datacp[k][2];
                    sum += m_datacp[k][2];

                    int endX = startX + (m_datacp[k][2] * width) / maxTime;

                    m_datacp[k][2] = 0;

                    dc.SetPen(calcPen);
                    dc.DrawLine(startX, y_offset + height / 3, endX, y_offset + height / 3);
                    dc.DrawLine(startX, y_offset + 2 * height / 3, endX, y_offset + 2 * height / 3);

                    timeStr = wxString::Format("%d", sum);
                    dc.DrawText(timeStr, endX - 2, y_offset + height);

                    k += 1;
                }
                else if (m_datacp[j][1] < m_datacp[k][2]) {
                    int startX = x_offset + (sum * width) / maxTime;

                    m_datacp[k][2] -= m_datacp[j][1];
                    sum += m_datacp[j][1];

                    int endX = startX + (m_datacp[j][1] * width) / maxTime;

                    m_datacp[j][1] = 0;

                    dc.SetPen(calcPen);
                    dc.DrawLine(startX, y_offset + 2 * height / 3, endX, y_offset + 2 * height / 3);
                    dc.DrawLine(startX, y_offset + height / 3, endX, y_offset + height / 3);

                    timeStr = wxString::Format("%d", sum);
                    dc.DrawText(timeStr, endX - 2, y_offset + height);

                    j += 1;
                }
                else {
                    int startX = x_offset + (sum * width) / maxTime;

                    sum += m_datacp[k][2];

                    int endX = startX + (m_datacp[j][1] * width) / maxTime;

                    m_datacp[j][1] = 0;
                    m_datacp[k][2] = 0;

                    dc.SetPen(calcPen);
                    dc.DrawLine(startX, y_offset + 2 * height / 3, endX, y_offset + 2 * height / 3);

                    timeStr = wxString::Format("%d", sum);
                    dc.DrawText(timeStr, endX - 2, y_offset + height);

                    dc.SetPen(calcPen);
                    dc.DrawLine(startX, y_offset + height / 3, endX, y_offset + height / 3);

                    k += 1;
                    j += 1;
                }
            }
        }
    }

    // 绘制抢占式多道程序的时间关系图
    void DrawPreemptiveMultithreadedChart(wxDC& dc, int x_offset, int y_offset, int width, int height) {
        int sum = 0;
        int n = m_data.size();

        // 黑色实线
        wxPen calcPen(wxColor(0, 0, 0), 2, wxPENSTYLE_SOLID);

        //虚线
        wxPen ioPen(wxColor(0, 0, 0), 0.5, wxPENSTYLE_DOT);


        //显示时间坐标数
        wxString timeStr = wxString::Format("%d", sum);

        // 深拷贝数据
        std::vector<std::vector<int>> m_datacp = m_data;

        int maxTime = 0; // 计算所有进程的总时间

        // 计算最大时间
        for (const auto& process : m_data) {
            maxTime += process[0] + process[1] + process[2];
        }

        //容器的名称
        int i = 0;
        int j = 0;
        int k = 0;

        while (k < n) {
            if (i == j && j == k) {

                int startX = x_offset + (sum * width) / maxTime;

                sum += m_datacp[i][0];

                int endX = startX + (m_datacp[i][0] * width) / maxTime;

                m_datacp[i][0] = 0;

                //实线
                dc.SetPen(calcPen);
                dc.DrawLine(startX, y_offset + height / 3, endX, y_offset + height / 3);

                //坐标轴数字
                timeStr = wxString::Format("%d", sum);
                dc.DrawText(timeStr, endX - 2, y_offset + height);

                i += 1;
            }
            else if (i < n && i > j && j == k) {
                if (m_datacp[i][0] > m_datacp[j][1]) {
                    int startX = x_offset + (sum * width) / maxTime;

                    m_datacp[i][0] -= m_datacp[j][1];
                    sum += m_datacp[j][1];

                    int endX = startX + (m_datacp[j][1] * width) / maxTime;

                    m_datacp[j][1] = 0;

                    dc.SetPen(calcPen);
                    dc.DrawLine(startX, y_offset + 2 * height / 3, endX, y_offset + 2 * height / 3);
                    dc.DrawLine(startX, y_offset + height / 3, endX, y_offset + height / 3);

                    timeStr = wxString::Format("%d", sum);
                    dc.DrawText(timeStr, endX - 2, y_offset + height);

                    j += 1;
                }
                else if (m_datacp[i][0] < m_datacp[j][1]) {
                    int startX = x_offset + (sum * width) / maxTime;

                    m_datacp[j][1] -= m_datacp[i][0];
                    sum += m_datacp[i][0];

                    int endX = startX + (m_datacp[i][0] * width) / maxTime;

                    m_datacp[i][0] = 0;

                    dc.SetPen(calcPen);
                    dc.DrawLine(startX, y_offset + height / 3, endX, y_offset + height / 3);
                    dc.DrawLine(startX, y_offset + 2 * height / 3, endX, y_offset + 2 * height / 3);

                    timeStr = wxString::Format("%d", sum);
                    dc.DrawText(timeStr, endX - 2, y_offset + height);

                    i += 1;
                }
                else {
                    int startX = x_offset + (sum * width) / maxTime;

                    sum += m_datacp[i][0];
                    m_datacp[i][0] = 0;

                    int endX = startX + (m_datacp[i][0] * width) / maxTime;

                    m_datacp[j][1] = 0;

                    dc.SetPen(calcPen);
                    dc.DrawLine(startX, y_offset + height / 3, endX, y_offset + height / 3);

                    timeStr = wxString::Format("%d", sum);
                    dc.DrawText(timeStr, endX - 2, y_offset + height);

                    dc.SetPen(calcPen);
                    dc.DrawLine(startX, y_offset + 2 * height / 3, endX, y_offset + 2 * height / 3);

                    i += 1;
                    j += 1;
                }
            }
            else if (i == n && i > j && j == k) {
                int startX = x_offset + (sum * width) / maxTime;

                sum += m_datacp[j][1];

                int endX = startX + (m_datacp[j][1] * width) / maxTime;

                m_datacp[j][1] = 0;

                dc.SetPen(calcPen);
                dc.DrawLine(startX, y_offset + 2 * height / 3, endX, y_offset + 2 * height / 3);

                timeStr = wxString::Format("%d", sum);
                dc.DrawText(timeStr, endX - 2, y_offset + height);

                j += 1;
            }
            else if (i < n && m_datacp[i][0] == 0 && i == j && j > k) {
                int startX = x_offset + (sum * width) / maxTime;

                sum += m_datacp[k][2];

                int endX = startX + (m_datacp[k][2] * width) / maxTime;

                m_datacp[k][2] = 0;

                dc.SetPen(calcPen);
                dc.DrawLine(startX, y_offset + height / 3, endX, y_offset + height / 3);

                timeStr = wxString::Format("%d", sum);
                dc.DrawText(timeStr, endX - 2, y_offset + height);

                k += 1;
            }
            else if (i < n && i == j && j > k) {
                int startX = x_offset + (sum * width) / maxTime;

                sum += m_datacp[k][2];

                int endX = startX + (m_datacp[k][2] * width) / maxTime;

                m_datacp[k][2] = 0;

                dc.SetPen(calcPen);
                dc.DrawLine(startX, y_offset + height / 3, endX, y_offset + height / 3);

                timeStr = wxString::Format("%d", sum);
                dc.DrawText(timeStr, endX - 2, y_offset + height);

                k += 1;
            }
            else if (i == n && i == j && j > k) {
                int startX = x_offset + (sum * width) / maxTime;

                sum += m_datacp[k][2];

                int endX = startX + (m_datacp[k][2] * width) / maxTime;

                m_datacp[k][2] = 0;

                dc.SetPen(calcPen);
                dc.DrawLine(startX, y_offset + height / 3, endX, y_offset + height / 3);

                timeStr = wxString::Format("%d", sum);
                dc.DrawText(timeStr, endX - 2, y_offset + height);

                k += 1;
            }
            else if (i > j && j > k) {
                if (m_datacp[j][1] > m_datacp[k][2]) {
                    int startX = x_offset + (sum * width) / maxTime;

                    m_datacp[j][1] -= m_datacp[k][2];
                    sum += m_datacp[k][2];

                    int endX = startX + (m_datacp[k][2] * width) / maxTime;

                    m_datacp[k][2] = 0;

                    dc.SetPen(calcPen);
                    dc.DrawLine(startX, y_offset + height / 3, endX, y_offset + height / 3);
                    dc.DrawLine(startX, y_offset + 2 * height / 3, endX, y_offset + 2 * height / 3);

                    timeStr = wxString::Format("%d", sum);
                    dc.DrawText(timeStr, endX - 2, y_offset + height);

                    k += 1;
                }
                else if (m_datacp[j][1] < m_datacp[k][2]) {
                    int startX = x_offset + (sum * width) / maxTime;

                    m_datacp[k][2] -= m_datacp[j][1];
                    sum += m_datacp[j][1];

                    int endX = startX + (m_datacp[j][1] * width) / maxTime;

                    m_datacp[j][1] = 0;

                    dc.SetPen(calcPen);
                    dc.DrawLine(startX, y_offset + 2 * height / 3, endX, y_offset + 2 * height / 3);
                    dc.DrawLine(startX, y_offset + height / 3, endX, y_offset + height / 3);

                    timeStr = wxString::Format("%d", sum);
                    dc.DrawText(timeStr, endX - 2, y_offset + height);

                    j += 1;
                }
                else {
                    int startX = x_offset + (sum * width) / maxTime;

                    sum += m_datacp[k][2];

                    int endX = startX + (m_datacp[j][1] * width) / maxTime;

                    m_datacp[j][1] = 0;
                    m_datacp[k][2] = 0;

                    dc.SetPen(calcPen);
                    dc.DrawLine(startX, y_offset + 2 * height / 3, endX, y_offset + 2 * height / 3);

                    timeStr = wxString::Format("%d", sum);
                    dc.DrawText(timeStr, endX - 2, y_offset + height);

                    dc.SetPen(calcPen);
                    dc.DrawLine(startX, y_offset + height / 3, endX, y_offset + height / 3);

                    k += 1;
                    j += 1;
                }
            }
        }
    }

    wxButton* m_button; // 加载CSV文件的按钮
    wxChoice* m_choice; // 选择显示模式的选择框
    std::vector<std::vector<int>> m_data; // 存储从CSV文件读取的数据
    int m_selectedMode; // 当前选择的显示模式
};

class MyApp : public wxApp {
public:
    virtual bool OnInit() {
        ChartFrame* frame = new ChartFrame("wxWidgets Chart Example");
        frame->Show(true);
        return true;
    }
};

wxIMPLEMENT_APP(MyApp);